<?php

// ------------------------------------------------------------------------
// |@Author       : Jarmin <edshop@qq.com>
// |@----------------------------------------------------------------------
// |@Date         : 2025-04-06 09:31:10
// |@----------------------------------------------------------------------
// |@LastEditTime : 2025-04-21 07:38:13
// |@----------------------------------------------------------------------
// |@LastEditors  : Jarmin <jarmin@ladmin.cn>
// |@----------------------------------------------------------------------
// |@Description  : CORS跨域中间件，处理跨域请求和API速率限制
// |@----------------------------------------------------------------------
// |@FilePath     : CorsMiddleware.php
// |@----------------------------------------------------------------------
// |@Copyright (c) 2025 http://www.ladmin.cn   All rights reserved.
// ------------------------------------------------------------------------
declare (strict_types=1);

namespace think\admin\middleware;

use think\Response;
use think\Request;

/**
 * CORS跨域中间件
 *
 * 主要功能：
 * 1. 处理跨域请求，设置CORS相关响应头
 * 2. 实现API请求速率限制
 * 3. 处理OPTIONS预检请求
 */
class CorsMiddleware
{
    // 速率限制配置（60次/分钟）
    protected $maxAttempts = 60;
    protected $decayMinutes = 1;
    protected $currentIp;

    /**
     * 中间件处理入口
     *
     * @param mixed $request 请求对象
     * @param \Closure $next 下一个中间件闭包
     * @return Response
     */
    public function handle($request, \Closure $next)
    {
        $this->currentIp = $request->ip();
        $key = "api_rate_limit:{$this->currentIp}";

        // 检查请求频率是否超过限制
        $attempts = cache($key) ?? 0;
        if ($attempts >= $this->maxAttempts) {
            return $this->createResponse(429, lang('request.api_too_frequent'));
        }

        // 更新请求计数
        $expireSeconds = $this->decayMinutes * 60;
        cache($key, $attempts + 1, $expireSeconds);

        // 处理OPTIONS预检请求
        if ($request->method(true) == 'OPTIONS') {
            return $this->createResponse(204);
        }

        // 继续处理请求并添加CORS头
        $response = $next($request);
        return $this->addCorsHeaders($response);
    }

    /**
     * 创建响应对象
     *
     * @param int $code HTTP状态码
     * @param string $message 响应消息
     * @return Response
     */
    private function createResponse(int $code, string $message = ''): Response
    {
        $response = $message ? response($message, $code) : response()->code($code);
        return $this->addCorsHeaders($response);
    }

    /**
     * 添加CORS相关响应头
     *
     * @param Response $response 响应对象
     * @return Response
     */
    private function addCorsHeaders(Response $response): Response
    {
        $current = cache("api_rate_limit:{$this->currentIp}") ?? 0;
        $remaining = max(0, $this->maxAttempts - $current);

        return $response->header([
            'Access-Control-Allow-Origin'  => '*',  // 允许所有域访问
            'Access-Control-Allow-Methods' => 'GET,POST,PUT,DELETE,PATCH,OPTIONS',  // 允许的HTTP方法
            'Access-Control-Allow-Headers' => 'Authorization, Content-Type, X-Requested-With',  // 允许的请求头
            'Access-Control-Max-Age'       => 3600,  // 预检请求缓存时间(秒)
            'X-RateLimit-Limit'     => $this->maxAttempts,  // 速率限制总数
            'X-RateLimit-Remaining' => $remaining,  // 剩余请求次数
            'X-RateLimit-Reset'     => time() + ($this->decayMinutes * 60)  // 限制重置时间
        ]);
    }
}
